#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "debug.h"
#include "os_api.h"
#include "ps_api.h"
#include "dev_api.h"
#include "mqttclient.h"

/*
server:   test.mosquitto.org

1883 : MQTT, unencrypted, unauthenticated
1884 : MQTT, unencrypted, authenticated
8883 : MQTT, encrypted, unauthenticated
*/


const char *mosquitto_org_crt = \
{
    \
    "-----BEGIN CERTIFICATE-----\r\n"
    "MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL\r\n" \
    "BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG\r\n" \
    "A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU\r\n" \
    "BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv\r\n" \
    "by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE\r\n" \
    "BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES\r\n" \
    "MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp\r\n" \
    "dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ\r\n" \
    "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg\r\n" \
    "UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW\r\n" \
    "Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA\r\n" \
    "s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH\r\n" \
    "3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo\r\n" \
    "E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT\r\n" \
    "MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV\r\n" \
    "6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\r\n" \
    "BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC\r\n" \
    "6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf\r\n" \
    "+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK\r\n" \
    "sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839\r\n" \
    "LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE\r\n" \
    "m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=\r\n"
    "-----END CERTIFICATE-----\r\n" \
};

const char *no_ca_crt = {"no_ca_crt"};  // 这个值不要修改，不带ca的tls，这样使用即可，详见mqtt库下network_init接口

#define MQTT_STACK_SIZE	(1024*3)

static void* mqtt_task_stack = NULL;
static OSTaskRef mqtt_task_ref = NULL;

static mqtt_client_t *client = NULL;

static void sub_topic_handle1(void *client, message_data_t *msg)
{
    (void)client;
    LOG_PRINTF("-----------------------------------------------------------------------------------");
    LOG_PRINTF("%s:%d %s()...\ntopic: %s\nmessage:%s", __FILE__, __LINE__, __FUNCTION__, msg->topic_name, (char *)msg->message->payload);
    LOG_PRINTF("-----------------------------------------------------------------------------------");
}

void mqtt_sample_tcp_unencrypted_unauthenticated(void)
{
    int rc = -1;

    LOG_PRINTF("%s()... mqtt test begin...", __FUNCTION__);

    client = mqtt_lease();

    mqtt_set_host(client, "test.mosquitto.org");
    mqtt_set_port(client, "1883");
    mqtt_set_client_id(client, "asr-mqtt-a5a5");
    mqtt_set_clean_session(client, 1);
	
    rc = mqtt_connect(client);	
    LOG_PRINTF("%s() mqtt_connect rc code:%d", __FUNCTION__, rc);

    rc = mqtt_subscribe(client, "test_over_tcp", QOS0, sub_topic_handle1);
    LOG_PRINTF("%s() mqtt_subscribe rc code:%d", __FUNCTION__, rc);

    while (1)
    {
        mqtt_message_t msg;
        memset(&msg, 0, sizeof(msg));

        msg.qos = QOS0;
        msg.payload = (void *)"this is a mqtt test over tcp...";

        rc = mqtt_publish(client, "test_over_tcp", &msg);
        LOG_PRINTF("%s() mqtt_publish rc code:%d", __FUNCTION__, rc);

        OSATaskSleep(2000);
    }
}

void mqtt_sample_tcp_unencrypted_authenticated(void)
{
    int rc = -1;

    LOG_PRINTF("%s()... mqtt test begin...", __FUNCTION__);

    client = mqtt_lease();

    mqtt_set_host(client, "test.mosquitto.org");
    mqtt_set_port(client, "1884");
    mqtt_set_user_name(client, "rw");
    mqtt_set_password(client, "readwrite");
    mqtt_set_client_id(client, "asr-mqtt-a5a5");
    mqtt_set_clean_session(client, 1);

    rc = mqtt_connect(client);
    LOG_PRINTF("%s() mqtt_connect rc code:%d", __FUNCTION__, rc);
    
    rc = mqtt_subscribe(client, "test_over_tcp_auth", QOS0, sub_topic_handle1);
    LOG_PRINTF("%s() mqtt_subscribe rc code:%d", __FUNCTION__, rc);

    while (1)
    {
        mqtt_message_t msg;
        memset(&msg, 0, sizeof(msg));

        msg.qos = QOS0;
        msg.payload = (void *)"this is a mqtt test over tcp and auth...";

        rc = mqtt_publish(client, "test_over_tcp_auth", &msg);
        LOG_PRINTF("%s() mqtt_publish rc code:%d", __FUNCTION__, rc);

        OSATaskSleep(2000);
    }
}

void mqtt_sample_tls_encrypted_unauthenticated(void)
{
    int rc = -1;

    LOG_PRINTF("%s()... mqtt test begin...", __FUNCTION__);

    client = mqtt_lease();

    mqtt_set_host(client, "test.mosquitto.org");
    //mqtt_set_port(client, "8883");
    mqtt_set_port(client, "8886");
    mqtt_set_client_id(client, "asr-mqtt-a5a5");

	mqtt_set_ca(client, (char*)no_ca_crt);	// 设置no ca,   MBEDTLS_SSL_VERIFY_NONE
	
    mqtt_set_clean_session(client, 1);

    rc = mqtt_connect(client);	
    LOG_PRINTF("%s() mqtt_connect rc code:%d", __FUNCTION__, rc);

    OSATaskSleep(100);
    rc = mqtt_subscribe(client, "test_over_tls", QOS0, sub_topic_handle1);
    LOG_PRINTF("%s() mqtt_subscribe rc code:%d", __FUNCTION__, rc);
    while (1)
    {
        mqtt_message_t msg;
        memset(&msg, 0, sizeof(msg));

        msg.qos = QOS0;
        msg.payload = (void *)"this is a mqtt test over tls...";

        rc = mqtt_publish(client, "test_over_tls", &msg);
        LOG_PRINTF("%s() mqtt_publish rc code:%d", __FUNCTION__, rc);        
        OSATaskSleep(2000);
    }
}

void mqtt_sample_tls_encrypted_unauthenticated_with_ca(void)
{
    int rc = -1;

    LOG_PRINTF("%s()... mqtt test begin...", __FUNCTION__);

    client = mqtt_lease();

    mqtt_set_host(client, "test.mosquitto.org");
    mqtt_set_port(client, "8883");

    mqtt_set_client_id(client, "asr-mqtt-a5a5");

	mqtt_set_ca(client, (char*)mosquitto_org_crt);	// 设置ca   MBEDTLS_SSL_VERIFY_REQUIRED
	
    mqtt_set_clean_session(client, 1);
    rc = mqtt_connect(client);
    LOG_PRINTF("%s() mqtt_connect rc code:%d", __FUNCTION__, rc);
    
    rc = mqtt_subscribe(client, "test_over_tls_ca", QOS0, sub_topic_handle1);
    LOG_PRINTF("%s() mqtt_subscribe rc code:%d", __FUNCTION__, rc);

    while (1)
    {
        mqtt_message_t msg;
        memset(&msg, 0, sizeof(msg));

        msg.qos = QOS0;
        msg.payload = (void *)"this is a mqtt test over tls with ca...";

        rc = mqtt_publish(client, "test_over_tls_ca", &msg);
        LOG_PRINTF("%s() mqtt_publish rc code:%d", __FUNCTION__, rc);       
        OSATaskSleep(2000);
    }
}

void wait_network_ready(void)
{
    int count = 30;
    while(count-- && ps_GetNetworkReady() == FALSE){	
        OSATaskSleep(200);
    }

    if (count <= 0){
        LOG_PRINTF("dev_CtrlReset.\n");
        dev_CtrlReset(0);
    }
}

static void mqtt_task(void *ptr)
{
    wait_network_ready();

    LOG_PRINTF("%s ps_GetNetworkReady is TRUE!", __FUNCTION__);

	//mqtt_sample_tcp_unencrypted_unauthenticated();
    //mqtt_sample_tcp_unencrypted_authenticated();
    mqtt_sample_tls_encrypted_unauthenticated();
    //mqtt_sample_tls_encrypted_unauthenticated_with_ca();
}


int main(void)
{	
	int ret;
	
	mqtt_task_stack = malloc(MQTT_STACK_SIZE);
	ASSERT(mqtt_task_stack != NULL);
	
    ret = OSATaskCreate(&mqtt_task_ref, mqtt_task_stack, MQTT_STACK_SIZE, 100, "mqtt_task", mqtt_task, NULL);
    ASSERT(ret == OS_SUCCESS);
	
	return 0;
}
